package com.hyy.lotterysystem.service.activitystatus.impl;

import com.hyy.lotterysystem.common.exception.ServiceException;
import com.hyy.lotterysystem.dao.mapper.ActivityMapper;
import com.hyy.lotterysystem.service.ActivityService;
import com.hyy.lotterysystem.service.activitystatus.ActivityStatusManager;
import com.hyy.lotterysystem.service.activitystatus.operater.AbstractActivityOperator;
import com.hyy.lotterysystem.service.dto.ConvertActivityStatusDTO;
import io.jsonwebtoken.lang.Collections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.hyy.lotterysystem.common.errorcode.ServiceErrorCodeConstants;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Service
public class ActivityStatusManagerImpl implements ActivityStatusManager {

    private static final Logger logger = LoggerFactory.getLogger(ActivityStatusManagerImpl.class);

    @Autowired
    private ActivityService activityService;




    //spring会自动把AbstractActivityOperator的子类（bean注册过）存放到这个map中，然后注入
    @Autowired
    private final Map<String, AbstractActivityOperator> operatorMap = new HashMap<>();


    /*
    * 按照规定好的策略进行状态转换
    * */
    @Override
    @Transactional(rollbackFor = Exception.class)//涉及多表，回滚
    public void handlerEvent(ConvertActivityStatusDTO convertActivityStatusDTO) {
        //1、状态扭转有依赖性
        //2、状态扭转条件的扩展

        if (Collections.isEmpty(operatorMap)) {
            logger.warn("operatorMap为空！");
            return;
        }


        Map<String, AbstractActivityOperator> curMap = new HashMap<>(operatorMap);
        Boolean update = false;


        //先处理：人员、奖品
        update = processConvertStatus(convertActivityStatusDTO, curMap, 1);


        //后活动

        update = processConvertStatus(convertActivityStatusDTO, curMap, 2) || update;

        //只要有一个模块状态转换，那么更新缓存
        if (update) {
            activityService.cacheActivity(convertActivityStatusDTO.getActivityId());
        }

    }

    //活动相关的 状态回滚（人、奖品、活动）
    @Override
    public void rollbackHandlerEvent(ConvertActivityStatusDTO convertActivityStatusDTO) {
        // operatorMap：活动、奖品、人员
        // 活动是否需要回滚？？ 绝对需要，
        // 原因：奖品都恢复成INIT，那么这个活动下的奖品绝对没抽完
        for (AbstractActivityOperator operator : operatorMap.values()) {
            operator.convert(convertActivityStatusDTO);
        }

        // 缓存更新
        activityService.cacheActivity(convertActivityStatusDTO.getActivityId());
    }

    /*给定sequence策略
    * 、判断status集合中元素是否符合该策略
    * 符合则进行转换
    * */
    private Boolean processConvertStatus(ConvertActivityStatusDTO
                                                 convertActivityStatusDTO,
                                         Map<String, AbstractActivityOperator>
                                                 curMap,
                                         int
                                                 sequence) {
        Boolean update = false;
        //遍历curMap
        Iterator<Map.Entry<String, AbstractActivityOperator>> iterator = curMap.entrySet().iterator();
        while (iterator.hasNext()) {
            AbstractActivityOperator operator = iterator.next().getValue();
            if (operator.sequence() != sequence//满足优先级
                    || !operator.needConvert(convertActivityStatusDTO)) {//并且状态确实需要转换
                continue;
            }

            //需要转换
            if (!operator.convert(convertActivityStatusDTO)) {
                logger.error("{}状态转换失败,", operator.getClass().getName());
                throw new ServiceException(ServiceErrorCodeConstants.ACTIVITY_STATUS_CONVERT_ERROR);

            }
            // currMap 删除当前 Operator(迭代器不用怕)
            iterator.remove();
            update = true;

        }


        //返回
        return update;
    }


}
